package net.plankton.agents.main;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.plankton.agents.Agent;
import net.plankton.agents.GenericAgent;
import net.plankton.context.Context;
import net.plankton.context.RiskContext;
import net.plankton.context.occurrence.Occurrence;
import net.plankton.events.EventProvider;
import net.plankton.events.GenericEventProvider;
import net.plankton.events.GenericOccurrence;
import net.plankton.selectors.Action;
import net.plankton.selectors.GenericSelector;

public class RulesEngine {

	private Map<String, EventProvider> providerRegistry = new HashMap<String, EventProvider>();
	
	private List<EventProvider> providers = new ArrayList<EventProvider>();
	
	private EventProvider currentProvider;
	private GenericOccurrence currentOccurrence;
	private Context context;
	
	private Agent currentAgent;
	
	private List<Agent> currentAgents = new ArrayList<Agent>();
	
	private int lastIndex=2;
	
	public RulesEngine() {
		context = new Context(new RiskContext(System.currentTimeMillis(),"Europe - Austria - Tyrol - Alpbach - Conference Center"),new StandardOutput());
	}
	
	
	public RulesEngine(SurveillanceOutput output) {
		context = new Context(new RiskContext(System.currentTimeMillis(),"Europe - Austria - Tyrol - Alpbach - Conference Center"),output);
	}
	public void registerProvider(String name,EventProvider prov) {
		providerRegistry.put(name, prov);
	}
	
	public void readFile(String path) {
		
		int count = 0;
		try {
			File f = new File(path);
			BufferedReader reader = new BufferedReader(new FileReader(f));
			String line=reader.readLine();
			while (line  !=null) {
				count++;
				parseLine(line);
				line =reader.readLine();
			}
		} catch (Exception e) {
			System.err.println("Error in file: "+path+" line: "+count);
			e.printStackTrace();
		}
		
		
		
	}

	public void start() {
		for (Iterator<EventProvider> it = providers.iterator();it.hasNext();) {
			it.next().start();
		}
	}
	
	private void parseLine(String line) {
		int i;
		for (i=0;line.charAt(i)=='\t';i++){}
		if (i==0) {
			line = line.trim();
			if (providerRegistry.containsKey(line)) {
				currentProvider = providerRegistry.get(line);
			}
			currentProvider = new GenericEventProvider();
			providers.add(currentProvider);
			currentOccurrence = null;
		}
		else if (i==1) {
			double percent = Double.parseDouble(line.substring(1,line.indexOf(' ')));
			String description = line.substring(line.indexOf(' ')+1);
			currentOccurrence = new GenericOccurrence(percent,description,context);
			currentProvider.addEvent(currentOccurrence);
			currentAgents = new ArrayList<Agent>();
		}
		else {
			try {
				Agent a;
				String description = line.substring(line.indexOf(' ')+1);
				int klIndex = description.indexOf('[');
				Action action=null;
				if (klIndex>-1) {
					String cmd = description.substring(klIndex+1,description.length()-1);
					description = description.substring(0,klIndex);
					
					action = new Action(cmd);
				}
				if (line.substring(line.lastIndexOf('\t')+1,line.lastIndexOf('\t')+2).equals("[")) {
					String cmd = line.substring(line.indexOf('[')+1,line.indexOf(']'));
					a = new GenericAgent(new GenericSelector(cmd),description,context);
					a.isRelevant();
				}
				else {
					double percent = Double.parseDouble(line.substring(line.lastIndexOf('\t')+1,line.indexOf(' ')));
					a = new GenericAgent(percent,description,context);
				}
				
				if (i==2)
					currentAgent=a;
				a.setAgent(currentAgent);
				if (action!=null)
					a.addAction(action);
				i=i-2;
				if (i==0) {
					currentOccurrence.addAgent(a);
					currentAgents.clear();
				}
				else if (i>lastIndex) {
					Agent a1 = currentAgents.get(lastIndex);
					a1.addAgent(a);
				}
				else if (i>=lastIndex) {
					for (int j=currentAgents.size()-1;j>i-1;j--) {
						currentAgents.remove(j);
					}
					Agent a1 = currentAgents.get(i-1);
					a1.addAgent(a);
				}
				currentAgents.add(i,a);
				lastIndex=i;
			}
			catch (Exception e) {
				Agent a = currentAgents.get(currentAgents.size()-1);
				double threatLevel = Double.parseDouble(line.substring(line.indexOf(' ')+1));
				a.setThreatLevel(threatLevel);
				
			}
		}
		
	}
	
	public static void main(String[] args) {
//		RulesEngine r = new RulesEngine(new ThreadedOutput(new StandardOutput()));
		RulesEngine r = new RulesEngine(new ThreadedNetOutput());
		r.readFile("/home/hacklm/workspaces/nemosomen/AlpbachRules/src/rules.txt");
		r.readFile("/home/hacklm/workspaces/nemosomen/AlpbachRules/src/kafka.txt");
		r.readFile("/home/hacklm/workspaces/nemosomen/AlpbachRules/src/computer.txt");
		r.start();
	}


	public void stop() {
		for (Iterator<EventProvider> it = providers.iterator();it.hasNext();) {
			it.next().end();
		}
		providers.clear();
	}
	
}
